# -*- coding: utf-8 -*-

# graphic-pppoe-client - Easy graphic networking manager
#
# Author: GoTLiuM InSPiRiT <gotlium@gmail.com>
#
# Copyright 2010, GoTLiuM InSPiRiT <gotlium@gmail.com>.
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2, as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranties of
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
# PURPOSE.  See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program.  If not, see <http://www.gnu.org/licenses/>.

from ConfigParser import RawConfigParser
import socket
import json
import sys
import os

class Client(object):
	def __init__(self):
		self.config = config = RawConfigParser()
		config.read('./config.cfg')
		host = config.get('Server', 'host')
		port = config.get('Server', 'port')

		try:
			self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
			self.sock.connect((host, int(port)))
		except:
			print "Can't connect to server."
			sys.exit(1)

	def send(self, message):
		response = readed = ""
		self.sock.send(str(message).strip() + '\n')
		while True:
			readed = self.sock.recv(1024)
			response += readed
			if not readed or readed[-1] == '\n':
				break
		return response

	def close(self):
		if self.sock:
			self.send('QUIT')
			self.sock.close()

class MainModules(object):
	def getMainModules(self):
		getMsg = {
			'Module': 'Main',
			'Action': 'getModules',
		}
		message = self.msgParse(
			self.send(json.dumps(getMsg))
		)
		if message[0] == "OK":
			try:
				print "getModules - OK"
				return json.loads(message[1])
			except:
				print "Modules: getMainModules - Can't load json data. Msg: %s" % message[1]
				sys.exit(1)
		else:
			print "Modules: getMainModules. Msg: %s" % message[1]
			sys.exit(1)

	def setMainActivity(self, modules):
		for module in modules['result']:
			# Unloading
			message = self.msgParse(
				self.send(json.dumps({
					'Module': 'Main',
					'Action': 'uloadModule',
					'module': module['alias']
				}))
			)
			if message[0] != "OK":
				print "Modules: Can't unload module. Message: %s" % message[1]
				sys.exit(1)
			if message[1] != 'Successful':
				print "Modules: uloadModule / Error result. Message: %s" % message[1]
				sys.exit(1)
			else:
				print "uloadModule - OK"

			# Loading
			message = self.msgParse(
				self.send(json.dumps({
					'Module': 'Main',
					'Action': 'loadModule',
					'module': module['alias']
				}))
			)
			if message[0] != "OK":
				print "Modules: Can't load module. Message: %s" % message[1]
				sys.exit(1)
			if message[1] != 'Successful':
				print "Modules: loadModule / Error result. Message: %s" % message[1]
				sys.exit(1)
			else:
				print "loadModule - OK"

			message = self.msgParse(
				self.send(json.dumps({
					'Module': 'Main',
					'Action': 'setEnabled',
					'module': module['alias'],
					'flag': 'false'
				}))
			)
			if message[0] != "OK":
				print "Modules: Can't set module status. Message: %s" % message[1]
				sys.exit(1)
			if message[1] != 'Successful':
				print "Modules: setEnabled=False / Error result. Message: %s" % message[1]
				sys.exit(1)
			else:
				print "setEnabled=False - OK"

			message = self.msgParse(
				self.send(json.dumps({
					'Module': 'Main',
					'Action': 'setEnabled',
					'module': module['alias'],
					'flag': 'true'
				}))
			)
			if message[0] != "OK":
				print "Modules: Can't set module status. Message: %s" % message[1]
				sys.exit(1)
			if message[1] != 'Successful':
				print "Modules: setEnabled=True / Error result. Message: %s" % message[1]
				sys.exit(1)
			else:
				print "setEnabled=True - OK"

			message = self.msgParse(
				self.send(json.dumps({
					'Module': 'Main',
					'Action': 'getAllModules',
				}))
			)
			if message[0] != "OK":
				print "Modules: Can't load all modules. Message: %s" % message[1]
				sys.exit(1)
			try:
				if not isinstance(json.loads(message[1]), dict):
					print "Modules: getAllModules / Error result. Message: %s" % message[1]
					sys.exit(1)
				else:
					print "getAllModules - OK"
			except:
				print "Modules: getAllModules / Can't load json data. Message: %s" % message[1]
				sys.exit(1)


	def testModules(self):
		self.banner("Main Modules tests starting")
		self.setMainActivity(
			self.getMainModules()
		)
		print "*"*50

class Module(object):
	createMsg = {
		'Action': 'createConnections',
		'data': {
			'use_firewall': 'false',
			'shared': 'false',
			'name': 'Test Connection',
			'type': 'dhcp',
			'if_name': 'eth0',
			'hwaddr': 'c8:0a:a9:f6:5b:1b',
			'dns_name': '8.8.8.8 8.8.4.4',
			'auto_connect': 'true',
			'auto_reconnect': 'true'
		}
	}

	def createConnection(self, module):
		self.createMsg['Module'] = module
		message = self.msgParse(
			self.send(json.dumps(self.createMsg))
		)
		if message[0] == "OK":
			if message[1].isdigit():
				print "createConnections - OK"
				return message[1]
			else:
				print "createConnections - Result error, Msg: %s" % message[1]
				sys.exit(1)
		else:
			print "createConnections - NO, Msg: %s" % message[1]
			sys.exit(1)

	def updateConnection(self, module, connId):
		updateMsg = self.createMsg
		updateMsg['data']['id'] = connId
		updateMsg['Module'] = module
		updateMsg['Action'] = 'updateConnections'
		message = self.msgParse(
			self.send(json.dumps(updateMsg))
		)
		if message[0] == "OK":
			if message[1] == 'True':
				print "updateConnections - OK"
				return message[1]
			else:
				print "updateConnections - Result error, Msg: %s" % message[1]
				sys.exit(1)
		else:
			print "updateConnections - NO, Msg: %s" % message[1]
			sys.exit(1)

	def getConnection(self, module, connId):
		getMsg = {
			'Module': module,
			'Action': 'getConnection',
			'connId': connId
		}
		message = self.msgParse(
			self.send(json.dumps(getMsg))
		)
		if message[0] == "OK":
			try:
				if isinstance(json.loads(message[1]), dict):
					print "getConnection - OK"
					return message[1]
				else:
					print "getConnection - Result error, Msg: %s" % message[1]
					sys.exit(1)
			except :
				print "getConnection - Can't dump result, Msg: %s" % message[1]
				sys.exit(1)
		else:
			print "getConnection - NO, Msg: %s" % message[1]
			sys.exit(1)

	def removeConnection(self, module, connId):
		delMsg = {
			'Module': module,
			'Action': 'deleteConnections',
			'data': int(connId)
		}
		message = self.msgParse(
			self.send(json.dumps(delMsg))
		)
		if message[0] == "OK":
			if message[1] == 'True':
				print "deleteConnections - OK"
				return message[1]
			else:
				print "deleteConnections - Result error, Msg: %s" % message[1]
				sys.exit(1)
		else:
			print "deleteConnections - NO, Msg: %s" % message[1]
			sys.exit(1)

	def testModule(self, module):
		self.banner("Module '%s' tests starting" % module)
		
		connId = self.createConnection(module)

		cdatas = self.getConnection(module, connId)
		if not self.compareData(self.createMsg['data'], json.loads(cdatas)):
			print "Data not equal to saved"
			sys.exit(1)

		self.updateConnection(module, connId)

		cdatas = self.getConnection(module, connId)
		if not self.compareData(self.createMsg['data'], json.loads(cdatas)):
			print "Data not equal to updated"
			sys.exit(1)

		for test in ('Routes', 'Users', 'Firewall', 'Ipconfigs'):
			t = TestBases(test, module, connId)
			del t

		self.removeConnection(module, connId)
		print "*"*50

class BaseForBases(object):

	baseReq = {
		"Module": None,
		"Action": None,
		"connId": None,
		"data": {}
	}

	def getMsg(self, case):
		case = case + self.testCase
		crtMsg = getattr(self, case)
		array = self.baseReq
		array['Module'] = self.module
		array['Action'] = case
		array['connId'] = self.connId
		array['data'] = crtMsg
		return array

	def create(self):
		message = self.msgParse(self.send(json.dumps(
			self.getMsg('create')
		)))
		if message[0] != 'OK':
			print "error"
			sys.exit(1)
		else:
			print "\t%s - OK" % self.baseReq['Action']
			return json.loads(message[1])

	def update(self):
		pass

	def delete(self, ids):
		self.baseReq['Action'] = 'delete' + self.testCase
		self.baseReq['data'] = ids
		message = self.msgParse(self.send(json.dumps(
			self.baseReq
		)))
		if message[0] != 'OK':
			print "error"
			sys.exit(1)
		else:
			print "\t%s - OK" % self.baseReq['Action']
			return message[1]

	def select(self):
		if 'data' in self.baseReq.keys():
			del self.baseReq['data']
		self.baseReq['Action'] = 'select' + self.testCase
		message = self.msgParse(self.send(json.dumps(
			self.baseReq
		)))
		if message[0] != 'OK':
			print "error"
		else:
			print "\t%s - OK" % self.baseReq['Action']
			return json.loads(message[1])

	def test(self):
		self.banner(
			'Base "%s" in "%s" scope checking. Connection id: %s' %
			(self.testCase, self.module, str(self.connId)), True
		)
		insIds = self.create()
		if(len(self.select()) != len(insIds)):
			print "Error length"
			sys.exit(1)
		self.delete(insIds)
		self.close()
		print "\t"+"*"*50
		print ""

class Helper(object):
	def compareData(self, old, new):
		for key in old.keys():
			if key not in new.keys():
				return False
			elif str(old[key]) != str(new[key]):
				return False
		return True

	def msgParse(self, msg):
		msg = str(msg.strip()).split(': ')
		return (msg[0], ': ' . join(msg[1:]))

	def banner(self, message, useTab = False):
		c = ""
		if useTab: c = "\t"
		print ""
		print c+"*"*50
		print c+message
		print c+"*"*50

class TestBases(Helper, Client, BaseForBases):
	module = None
	connId = None
	createRoutes = [
		{
			'netmask': '255.255.255.0',
			'destination': '192.168.2.255',
			'gateway': '192.168.0.1'
		},
		{
			'netmask': '255.255.255.0',
			'destination': '192.168.3.255',
			'gateway': '192.168.0.1'
		}
	]

	createUsers = [
		{
			'user_ip': '192.168.1.7',
			'user_mac': '5c:ac:4c:7d:91:0d'
		},
		{
			'user_ip': '192.168.1.8',
			'user_mac': '5c:ac:4c:7d:91:0d'
		}
	]

	createFirewall = [
		{
			"port": 80
		},
		{
			"port": 8080
		}
	]

	createIpconfigs = [
		{
			'ip_address': '192.168.1.2',
			'netmask': '255.255.255.0',
			'gateway': '192.168.1.1'
		},
		{
			'ip_address': '192.168.1.3',
			'netmask': '255.255.255.0',
			'gateway': ''
		}
	]

	def __init__(self, case, module, connId):
		Client.__init__(self)
		self.connId = connId
		self.module = module
		self.testCase = case
		self.send('EXCHANGE')
		self.test()

class Test(Helper, Client, MainModules, Module):
	def run(self):
		os.system('reset')
		self.send('EXCHANGE')
		self.testModules()
		self.testModule('Wired')
		self.close()
		print ""

if __name__ == '__main__':
	test = Test()
	test.run()
